import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';

class Hexie {
  static const _endFlag = 'end';

  final _wordMapCompleter = Completer<Map<String, dynamic>>();
  final _wordMap = HashMap<String, dynamic>();

  Future<void> build(Iterable<File> files) async {
    if (_wordMapCompleter.isCompleted) {
      return;
    }

    for (final file in files) {
      await appendDic(file);
    }

    _wordMapCompleter.complete(_wordMap);
  }

  Future<void> appendDic(File file) async {
    final lines =
        file.openRead().transform(utf8.decoder).transform(const LineSplitter());

    await for (final line in lines) {
      appendWord(line);
    }
  }

  void appendWords(Iterable<String> wordSet) {
    for (String word in wordSet) {
      appendWord(word);
    }
  }

  // 将敏感词放入Map中，构建一个DFA算法模型
  void appendWord(String word) {
    if (word?.isNotEmpty != true) return;

    Map<String, dynamic> currMap = _wordMap;

    for (int i = 0; i < word.length; i++) {
      final char = word[i].toLowerCase();

      currMap = currMap.putIfAbsent(char, () {
        return HashMap<String, dynamic>();
      });
    }

    currMap[_endFlag] = true;
  }

  Future<StringBuffer> firstSensitive(
    String text, {
    int startIndex = 0,
    StringBuffer buffer,
  }) async {
    buffer ??= StringBuffer();

    for (int i = startIndex; i < text.length; i++) {
      buffer.clear();
      final result = await startWithSensitive(
        text,
        startIndex: i,
        buffer: buffer,
      );
      if (result != null) return result;
    }

    return null;
  }

  Future<StringBuffer> startWithSensitive(
    String text, {
    int startIndex = 0,
    StringBuffer buffer,
  }) async {
    buffer ??= StringBuffer();

    Map<String, dynamic> map = await _wordMapCompleter.future;
    for (int i = startIndex; i < text.length; i++) {
      final char = text[i].toLowerCase();

      map = map[char];
      if (map == null) {
        return null;
      }

      buffer.write(char);
      if (map[_endFlag] == true) {
        // 匹配完毕，确认敏感
        return buffer;
      }
    }

    return null;
  }
}
